<script lang="ts" setup>
import type {
  VxeGridListeners,
  VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { OperationLogApi } from '#/api/types/modules/operationLog';

import { h, onMounted, ref } from 'vue';
import VueJsonPretty from 'vue-json-pretty';
import 'vue-json-pretty/lib/styles.css';

import { Page } from '@vben/common-ui';

import {
  Badge,
  Descriptions,
  DescriptionsItem,
  Drawer,
  Tag,
} from 'ant-design-vue';

import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
  getOperationLogListApi,
  getOperationTypeListApi,
} from '#/api/core/modules/operationLog';

const operationTypes = ref<{ color?: string; label: string; value: number }[]>(
  [],
);

onMounted(async () => {
  try {
    const res = await getOperationTypeListApi();
    // 将返回的Map数据转换为数组并排序
    const typesArray: { color?: string; label: string; value: number }[] = [];

    // 处理后端返回的数据
    Object.entries(res.data).forEach(([key, value]) => {
      // 根据不同类型设置不同颜色
      let color: string;
      const valueNum = Number.parseInt(key);
      switch (valueNum) {
        case 0: {
          color = 'gray';
          break;
        }
        case 1: {
          color = 'green';
          break;
        }
        case 2: {
          color = 'orange';
          break;
        }
        case 3: {
          color = 'red';
          break;
        }
        default: {
          color = 'default';
        }
      }

      typesArray.push({
        label: value as string,
        value: valueNum,
        color,
      });
    });

    // 按value值排序
    typesArray.sort((a, b) => a.value - b.value);
    operationTypes.value = typesArray;
  } catch (error) {
    console.error('获取操作类型列表失败', error);
  }
});

// 表格事件监听
const gridEvents: VxeGridListeners<OperationLogApi.OperationLogVO> = {
  // 这里可以添加表格事件
};

// 表格组件
const [Grid] = useVbenVxeGrid({
  formOptions: {
    fieldMappingTime: [['operationTime', ['startTime', 'endTime']]],
    collapsed: true,
    // 表单配置
    schema: [
      {
        component: 'Input',
        fieldName: 'systemModule',
        label: '系统模块',
      },
      {
        component: 'Select',
        componentProps: {
          allowClear: true,
          options: [
            { label: '成功', value: 1 },
            { label: '失败', value: 0 },
          ],
        },
        fieldName: 'status',
        label: '操作状态',
      },
      {
        component: 'Select',
        componentProps: {
          allowClear: true,
          options: operationTypes,
        },
        fieldName: 'operationType',
        label: '操作类型',
      },
      {
        component: 'Input',
        fieldName: 'operator',
        label: '操作人',
      },
      {
        component: 'Input',
        fieldName: 'ipAddress',
        label: 'IP地址',
      },
      {
        component: 'RangePicker',
        fieldName: 'operationTime',
        label: '操作时间',
      },
    ],
  },
  gridEvents,
  // 表格配置
  gridOptions: {
    columns: [
      {
        field: 'systemModule',
        title: '系统模块',
      },
      {
        field: 'operationType',
        title: '操作类型',
        slots: {
          default: ({ row }) => {
            const typeItem = operationTypes.value.find(
              (item) => item.value === Number(row.operationType),
            );
            const color = typeItem?.color || 'default';
            const label = typeItem?.label || row.operationType;
            return h(Tag, { color }, () => label);
          },
        },
      },
      {
        field: 'operatorName',
        title: '操作人',
      },
      {
        field: 'ipAddress',
        title: 'IP地址',
      },
      {
        field: 'ipInfo',
        title: 'IP信息',
        showOverflow: true,
      },
      {
        field: 'operationStatus',
        title: '操作状态',
        width: 100,
        cellRender: {
          name: 'CellTag',
          attrs: {
            map: {
              0: { label: '失败', color: 'red' },
              1: { label: '成功', color: 'green' },
            },
          },
        },
      },
      {
        field: 'operationTime',
        title: '操作时间',
        width: 180,
      },
      {
        field: 'operationDuration',
        title: '操作耗时(ms)',
        width: 120,
      },
      {
        align: 'center',
        cellRender: {
          attrs: {
            actions: [
              {
                code: 'detail',
                name: '查看详情',
              },
            ],
            onClick: onActionClick,
          },
          name: 'CellOperation',
        },
        field: 'operation',
        title: '操作',
        width: 120,
      },
    ],
    height: 'auto',
    keepSource: true,
    proxyConfig: {
      ajax: {
        query: async ({ page }, formValues) => {
          const result = await getOperationLogListApi({
            current: page.currentPage,
            pageSize: page.pageSize,
            ...formValues,
          });
          return result.data;
        },
      },
    },
    rowConfig: {
      keyField: 'id',
      isHover: true,
    },
    toolbarConfig: {
      custom: true,
      export: false,
      refresh: { code: 'query' },
      search: true,
      zoom: true,
    },
  } as VxeTableGridOptions<OperationLogApi.OperationLogVO>,
});

const showDrawer = ref(false);
const drawerRow = ref<null | OperationLogApi.OperationLogVO>(null);

// 操作按钮点击处理
function onActionClick(e: {
  code: string;
  row: OperationLogApi.OperationLogVO;
}) {
  switch (e.code) {
    case 'detail': {
      showLogDetail(e.row);
      break;
    }
  }
}

// 用抽屉展示日志详情
function showLogDetail(row: OperationLogApi.OperationLogVO) {
  drawerRow.value = row;
  showDrawer.value = true;
}

function closeDrawer() {
  showDrawer.value = false;
}

// 工具函数：安全解析JSON字符串
function parseIfJson(val: any) {
  if (typeof val === 'string') {
    try {
      return JSON.parse(val);
    } catch {
      return val;
    }
  }
  return val;
}
</script>

<template>
  <Page auto-content-height>
    <Grid table-title="操作日志列表" />
    <Drawer
      :visible="showDrawer"
      :width="600"
      title="查看日志"
      :closable="false"
      @close="closeDrawer"
      placement="right"
    >
      <Descriptions
        bordered
        :column="1"
        size="small"
        v-if="drawerRow"
        :label-style="{ width: '120px' }"
        class="pd-0,mg-0"
      >
        <DescriptionsItem label="日志编号">{{ drawerRow.id }}</DescriptionsItem>
        <DescriptionsItem label="操作结果">
          <Badge
            :status="
              Number(drawerRow.operationStatus) === 1 ? 'success' : 'error'
            "
            :text="Number(drawerRow.operationStatus) === 1 ? '成功' : '失败'"
          />
        </DescriptionsItem>
        <DescriptionsItem label="操作模块">
          <Tag>{{ drawerRow.systemModule }}</Tag>
        </DescriptionsItem>
        <DescriptionsItem label="操作类型">
          <Tag>
            {{
              operationTypes.find(
                (item) => item.value === Number(drawerRow?.operationType),
              )?.label
            }}
          </Tag>
        </DescriptionsItem>
        <DescriptionsItem label="操作信息">
          账号: {{ drawerRow.operatorName }} / {{ drawerRow.ipAddress }} /
          {{ drawerRow.ipInfo }}
        </DescriptionsItem>
        <DescriptionsItem label="请求信息">
          <Tag color="blue">{{ drawerRow.requestMethod }}</Tag>
          {{ drawerRow.requestUrl }}
        </DescriptionsItem>
        <DescriptionsItem label="方法">
          {{ drawerRow.methodPath }}
        </DescriptionsItem>
        <DescriptionsItem label="请求参数">
          <VueJsonPretty
            :data="parseIfJson(drawerRow.requestParams)"
            :deep="3"
          />
        </DescriptionsItem>
        <DescriptionsItem label="响应参数">
          <VueJsonPretty
            :data="parseIfJson(drawerRow.responseParams)"
            :deep="3"
          />
        </DescriptionsItem>
        <DescriptionsItem label="执行异常">
          {{ drawerRow.errorMessage }}
        </DescriptionsItem>
        <DescriptionsItem label="请求耗时">
          {{ drawerRow.operationDuration }} ms
        </DescriptionsItem>
        <DescriptionsItem label="操作时间">
          {{
            typeof drawerRow.operationTime === 'string'
              ? drawerRow.operationTime
              : drawerRow.operationTime.toString()
          }}
        </DescriptionsItem>
      </Descriptions>
    </Drawer>
  </Page>
</template>

<style lang="less" scoped>
.log-detail-simple {
  background: #fff;
  padding: 24px 32px;
  font-size: 15px;
  color: #222;

  .log-line {
    margin-bottom: 12px;
    display: flex;
    align-items: flex-start;
    white-space: pre-wrap;
    word-break: break-all;

    .log-label {
      font-weight: bold;
      min-width: 100px;
      margin-right: 8px;
      color: #333;
      display: inline-block;
    }

    .log-pre {
      background: #f5f5f5;
      border-radius: 4px;
      padding: 8px;
      margin: 0;
      font-size: 13px;
      width: 100%;
      max-width: 100%;
      overflow-x: auto;
    }
  }
}
</style>
